<!DOCTYPE html>
<html lang="en-us">
  <head>
    
    <script type="application/ld+json">

{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "Service",
  
  "datePublished": "2022-04-01T20:38:20+08:00",
  "dateModified": "2022-04-01T20:38:20+08:00",
  "author": {
    "@type": "Person",
    "name": "Zhang Gaojie",
    
    "image": "https://zgjoget.gitee.io/img/avatar.jpg"
    
  },
  "mainEntityOfPage": { 
    "@type": "WebPage",
    "@id": "https:\/\/zgjoget.gitee.io\/2022\/04\/service\/" 
  },
  "publisher": {
    "@type": "Organization",
    "name": "Zhang Gaojie",
    
    "logo": {
      "@type": "ImageObject",
      "url": "https://zgjoget.gitee.io/img/avatar.jpg"
    }
    
  },
  "description": "后台默默的劳动者，探究Service\n",
  "keywords": []
}

</script>
    <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="generator" content="Hugo 0.92.2 with theme Tranquilpeak 0.5.3-BETA">
<meta name="author" content="Zhang Gaojie">
<meta name="keywords" content="">
<meta name="description" content="后台默默的劳动者，探究Service">


<meta property="og:description" content="后台默默的劳动者，探究Service">
<meta property="og:type" content="article">
<meta property="og:title" content="Service">
<meta name="twitter:title" content="Service">
<meta property="og:url" content="https://zgjoget.gitee.io/2022/04/service/">
<meta property="twitter:url" content="https://zgjoget.gitee.io/2022/04/service/">
<meta property="og:site_name" content="Zhang Gaojie">
<meta property="og:description" content="后台默默的劳动者，探究Service">
<meta name="twitter:description" content="后台默默的劳动者，探究Service">
<meta property="og:locale" content="en-us">

  
    <meta property="article:published_time" content="2022-04-01T20:38:20">
  
  
    <meta property="article:modified_time" content="2022-04-01T20:38:20">
  
  
  
  


<meta name="twitter:card" content="summary">







  <meta property="og:image" content="https://zgjoget.gitee.io/img/avatar.jpg">
  <meta property="twitter:image" content="https://zgjoget.gitee.io/img/avatar.jpg">






    <title>Service</title>

    <link rel="icon" href="https://zgjoget.gitee.io/favicon.png">
    

    

    <link rel="canonical" href="https://zgjoget.gitee.io/2022/04/service/">

    
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css" integrity="sha512-H9jrZiiopUdsLpg94A333EfumgUBpO9MdbxStdeITo+KEIMaNfHNvwyjjDJb+ERPaRS6DpyRlKbvPUasNItRyw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    
    
    
    <link rel="stylesheet" href="https://zgjoget.gitee.io/css/style-h6ccsoet3mzkbb0wngshlfbaweimexgqcxj0h5hu4h82olsdzz6wmqdkajm.min.css" />
    
    

    
      
    
    
  </head>

  <body>
    <div id="blog">
      <header id="header" data-behavior="4">
  <i id="btn-open-sidebar" class="fa fa-lg fa-bars"></i>
  <div class="header-title">
    <a class="header-title-link" href="https://zgjoget.gitee.io/" aria-label="Go to homepage">Zhang Gaojie</a>
  </div>
  
    
      <a class="header-right-picture "
         href="https://zgjoget.gitee.io/#about" aria-label="Open the link: /#about">
    
    
    
      
        <img class="header-picture" src="https://zgjoget.gitee.io/img/avatar.jpg" alt="Author&#39;s picture" />
      
    
    </a>
  
</header>

      <nav id="sidebar" data-behavior="4">
  <div class="sidebar-container">
    
      <div class="sidebar-profile">
        <a href="https://zgjoget.gitee.io/#about" aria-label="Read more about the author">
          <img class="sidebar-profile-picture" src="https://zgjoget.gitee.io/img/avatar.jpg" alt="Author&#39;s picture" />
        </a>
        <h4 class="sidebar-profile-name">Zhang Gaojie</h4>
        
          <h5 class="sidebar-profile-bio">A Computer-science and Cyber-security novice</h5>
        
      </div>
    
    <ul class="sidebar-buttons">
      
  <li class="sidebar-button">
    
      <a class="sidebar-button-link " href="https://zgjoget.gitee.io/" title="Home">
    
      <i class="sidebar-button-icon fas fa-lg fa-home" aria-hidden="true"></i>
      
      <span class="sidebar-button-desc">Home</span>
    </a>
  </li>

  <li class="sidebar-button">
    
      <a class="sidebar-button-link " href="https://zgjoget.gitee.io/categories" title="Categories">
    
      <i class="sidebar-button-icon fas fa-lg fa-bookmark" aria-hidden="true"></i>
      
      <span class="sidebar-button-desc">Categories</span>
    </a>
  </li>

  <li class="sidebar-button">
    
      <a class="sidebar-button-link " href="https://zgjoget.gitee.io/tags" title="Tags">
    
      <i class="sidebar-button-icon fas fa-lg fa-tags" aria-hidden="true"></i>
      
      <span class="sidebar-button-desc">Tags</span>
    </a>
  </li>

  <li class="sidebar-button">
    
      <a class="sidebar-button-link " href="https://zgjoget.gitee.io/archives" title="Archives">
    
      <i class="sidebar-button-icon fas fa-lg fa-archive" aria-hidden="true"></i>
      
      <span class="sidebar-button-desc">Archives</span>
    </a>
  </li>

  <li class="sidebar-button">
    
      <a class="sidebar-button-link " href="https://zgjoget.gitee.io/#about" title="About">
    
      <i class="sidebar-button-icon fas fa-lg fa-question" aria-hidden="true"></i>
      
      <span class="sidebar-button-desc">About</span>
    </a>
  </li>


    </ul>
    <ul class="sidebar-buttons">
      
  <li class="sidebar-button">
    
      <a class="sidebar-button-link " href="https://github.com/zgjoget9" target="_blank" rel="noopener" title="GitHub">
    
      <i class="sidebar-button-icon fab fa-lg fa-github" aria-hidden="true"></i>
      
      <span class="sidebar-button-desc">GitHub</span>
    </a>
  </li>

  <li class="sidebar-button">
    
      <a class="sidebar-button-link " href="https://stackoverflow.com/users/18013715/jack-zhang" target="_blank" rel="noopener" title="Stack Overflow">
    
      <i class="sidebar-button-icon fab fa-lg fa-stack-overflow" aria-hidden="true"></i>
      
      <span class="sidebar-button-desc">Stack Overflow</span>
    </a>
  </li>


    </ul>
    <ul class="sidebar-buttons">
      

    </ul>
  </div>
</nav>

      

      <div id="main" data-behavior="4"
        class="
               hasCoverMetaIn
               ">
        <article class="post" id="top">
          
          
            <div class="post-header main-content-wrap text-left">
  
    <h1 class="post-title">
      Service
    </h1>
  
  
  <div class="postShorten-meta post-meta">
    
      <time datetime="2022-04-01T20:38:20&#43;08:00">
        
  April 1, 2022

      </time>
    
    
  </div>

</div>
          
          <div class="post-content markdown">
            <div class="main-content-wrap">
              <p>后台默默的劳动者，探究Service</p>
<h2 id="service是什么">service是什么</h2>
<p>Service是Android中实现程序后台运行的解决方案，它非常适合执行那些不需要和用户交互而且还要求长期运行的任务。Service的运行不依赖于任何用户界面，即使程序被切换到后台，或者用户打开了另外一个应用程序，Service仍然能够保持正常运行。</p>
<p>另外，不要被Service的后台概念所迷惑，实际上Service并不会自动开启线程，所有的代码都是默认运行在主线程当中的。也就是说，我们需要在Service的内部手动创建子线程，并在这里执行具体的任务，否则就有可能出现主线程被阻塞的情况。</p>
<h2 id="android多线程编程">android多线程编程</h2>
<h3 id="线程的基本用法">线程的基本用法</h3>
<p>Android多线程编程其实并不比Java多线程编程特殊，基本是使用相同的语法。比如，定义一个线程只需要新建一个类继承自Thread，然后重写父类的run()方法，并在里面编写耗时逻辑即可，如下所示：</p>
<pre tabindex="0"><code>class MyThread : Thread() {
    override fun run() {
        // 编写具体的逻辑
    }
}
</code></pre><p>启动这个线程只需要创建MyThread的实例，然后调用它的start()方法即可，这样run()方法中的代码就会在子线程当中运行了，如下所示：</p>
<pre tabindex="0"><code>MyThread().start()
</code></pre><p>Kotlin还给我们提供了一种更加简单的开启线程的方式，写法如下：</p>
<pre tabindex="0"><code>thread {
    // 编写具体的逻辑
}
</code></pre><h3 id="在子线程中更新ui">在子线程中更新UI</h3>
<p>Android的UI是线程不安全的，也就是说，如果想要更新应用程序里的UI元素，必须在主线程中进行，否则就会出现异常。对于这种情况，Android提供了一套异步消息处理机制，完美地解决了在子线程中进行UI操作的问题。</p>
<pre tabindex="0"><code>class MainActivity : AppCompatActivity() {

    val updateText = 1

    val handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            // 在这里可以进行UI操作
            when (msg.what) {
                updateText -&gt; textView.text = &quot;Nice to meet you&quot;
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        changeTextBtn.setOnClickListener {
            thread {
                val msg = Message()
                msg.what = updateText
                handler.sendMessage(msg) // 将Message对象发送出去
            }
        }
    }

}
</code></pre><h3 id="解析异步消息处理机制">解析异步消息处理机制</h3>
<p>Android中的异步消息处理主要由4个部分组成：Message、Handler、MessageQueue和Looper。</p>
<ul>
<li>
<p>Message是在线程之间传递的消息，它可以在内部携带少量的信息，用于在不同线程之间传递数据。</p>
</li>
<li>
<p>Handler主要用于发送和处理消息，发送消息一般是使用Handler的sendMessage()方法、post()方法等，而发出的消息经过一系列地辗转处理后，最终会传递到Handler的handleMessage()方法中。</p>
</li>
<li>
<p>MessageQueue是消息队列的意思，它主要用于存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中，等待被处理。每个线程中只会有一个MessageQueue对象。</p>
</li>
<li>
<p>Looper是每个线程中的MessageQueue的管家，调用Looper的loop()方法后，就会进入一个无限循环当中，然后每当发现MessageQueue中存在一条消息时，就会将它取出，并传递到Handler的handleMessage()方法中。每个线程中只会有一个Looper对象。</p>
</li>
</ul>
<p>异步消息处理机制流程示意图如下所示：</p>
<p><img src="https://zgjoget9.github.io/img/service_1.png" alt="pic1"></p>
<h2 id="service的基本用法">Service的基本用法</h2>
<h3 id="定义一个service">定义一个Service</h3>
<p>右键项目的任何包路径→New→Service→Service，会弹出如右图所示的窗口。</p>
<p>Exported属性表示是否将这个Service暴露给外部其他程序访问。</p>
<p>Enabled属性表示是否启用这个Service。</p>
<p>点击“ Finish”完成创建。</p>
<p><img src="https://zgjoget9.github.io/img/service_2.png" alt="pic2"></p>
<h3 id="重写service">重写service</h3>
<p>然后需要重写了onCreate()、onStartCommand()和onDestroy()这3个方法。其中onCreate()方法会在Service创建的时候调用，onStartCommand()方法会在每次Service启动的时候调用，onDestroy()方法会在Service销毁的时候调用。</p>
<pre tabindex="0"><code>class MyService : Service() {
    …
    override fun onCreate() {
        super.onCreate()
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onDestroy() {
        super.onDestroy()
    }

}
</code></pre><h3 id="在androidmanifest文件中注册">在AndroidManifest文件中注册</h3>
<p>另外需要注意，每一个Service都需要在AndroidManifest.xml文件中进行注册才能生效，这是Android四大组件共有的特点。</p>
<pre tabindex="0"><code>&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    package=&quot;com.example.servicetest&quot;&gt;

    &lt;application …&gt;
        ...
        &lt;service
            android:name=&quot;.MyService&quot;
            android:enabled=&quot;true&quot;
            android:exported=&quot;true&quot;&gt;
        &lt;/service&gt;
    &lt;/application&gt;

&lt;/manifest&gt;
</code></pre><h3 id="启动和停止service">启动和停止Service</h3>
<p>Context类中提供了startService()和stopService()这两个方法来启动和停止Service，所以我们在Activity里可以直接调用这两个方法。</p>
<pre tabindex="0"><code>class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        startServiceBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            startService(intent) // 启动Service
        }
        stopServiceBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            stopService(intent) // 停止Service
        }
    }
    
}
</code></pre><h3 id="activity和service进行通信">Activity和Service进行通信</h3>
<p>假如我们希望在MyService里提供一个下载功能，然后在Activity中可以决定何时开始下载，以及随时查看下载进度。实现这个功能的思路是创建一个专门的Binder对象来对下载功能进行管理。</p>
<pre tabindex="0"><code>class MyService : Service() {

    private val mBinder = DownloadBinder()

    class DownloadBinder : Binder() {

        fun startDownload() {
            Log.d(&quot;MyService&quot;, &quot;startDownload executed&quot;)
        }

        fun getProgress(): Int {
            Log.d(&quot;MyService&quot;, &quot;getProgress executed&quot;)
            return 0
        }

    }

    override fun onBind(intent: Intent): IBinder {
        return mBinder
    }
    …
}
</code></pre><p>当一个Activity和Service绑定了之后，就可以调用该Service里的Binder提供的方法了，如下所示：</p>
<pre tabindex="0"><code>class MainActivity : AppCompatActivity() {

    lateinit var downloadBinder: MyService.DownloadBinder

    private val connection = object : ServiceConnection {

        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            downloadBinder = service as MyService.DownloadBinder
            downloadBinder.startDownload()
            downloadBinder.getProgress()
        }

        override fun onServiceDisconnected(name: ComponentName) {
        }

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        …
        bindServiceBtn.setOnClickListener {
            val intent = Intent(this, MyService::class.java)
            bindService(intent, connection, Context.BIND_AUTO_CREATE) // 绑定Service
        }
        unbindServiceBtn.setOnClickListener {
            unbindService(connection) // 解绑Service
        }
    }

}
</code></pre><h2 id="service的更多技巧">Service的更多技巧</h2>
<h3 id="前台service">前台Service</h3>
<p>前台Service和普通Service最大的区别就在于，它会一直有一个正在运行的图标在系统的状态栏显示，下拉状态栏后可以看到更加详细的信息，非常类似于通知的效果。</p>
<p>由于状态栏中一直有一个正在运行的图标，相当于我们的应用以另外一种形式保持在前台可见状态，所以系统不会倾向于回收前台Service。</p>
<p><img src="https://zgjoget9.github.io/img/service_3.png" alt="pic3"></p>
<h3 id="创建前台service">创建前台Service</h3>
<p>在MyService中编写如下代码：</p>
<pre tabindex="0"><code>class MyService : Service() {
    …
    override fun onCreate() {
        super.onCreate()
        val manager = getSystemService(Context.NOTIFICATION_SERVICE) asNotificationManager
        if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(&quot;my_service&quot;, &quot;前台Service通知&quot;, NotificationManager.IMPORTANCE_DEFAULT)
            manager.createNotificationChannel(channel)
        }
        val intent = Intent(this, MainActivity::class.java)
        val pi = PendingIntent.getActivity(this, 0, intent, 0)
        val notification = NotificationCompat.Builder(this, &quot;my_service&quot;)
            .setContentTitle(&quot;This is content title&quot;)
            .setContentText(&quot;This is content text&quot;)
            .setSmallIcon(R.drawable.small_icon)
            .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.large_icon))
            .setContentIntent(pi)
            .build()
        startForeground(1, notification)
    }
    …
}
</code></pre><h3 id="在androidmanifest文件中声明权限">在AndroidManifest文件中声明权限</h3>
<p>另外，从Android 9.0系统开始，使用前台Service必须在AndroidManifest.xml文件中进行权限声明才行，如下所示：</p>
<pre tabindex="0"><code>&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
          package=&quot;com.example.servicetest&quot;&gt;
    &lt;uses-permission android:name=&quot;android.permission.FOREGROUND_SERVICE&quot; /&gt;
    …
&lt;/manifest&gt;
</code></pre><h3 id="实现前台service效果">实现前台Service效果</h3>
<p>现在MyService就会以前台Service的模式启动了，并且在系统状态栏会显示一个通知图标，下拉状态栏后可以看到该通知的详细内容。</p>
<p><img src="https://zgjoget9.github.io/img/service_4.png" alt="pic4"></p>
<h3 id="intentservice">IntentService</h3>
<p>Android专门提供了一个IntentService，用于简单地创建一个异步的、会自动停止的Service。</p>
<pre tabindex="0"><code>class MyIntentService : IntentService(&quot;MyIntentService&quot;) {

    override fun onHandleIntent(intent: Intent?) {
        // 打印当前线程的id
        Log.d(&quot;MyIntentService&quot;, &quot;Thread id is ${Thread.currentThread().name}&quot;)
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(&quot;MyIntentService&quot;, &quot;onDestroy executed&quot;)
    }

}
</code></pre><p>其中，onHandleIntent()方法会运行在子线程当中，并且IntentService会在任务执行完成后自动结束，因而onDestroy()方法将会执行。</p>
              


            </div>
          </div>
          <div id="post-footer" class="post-footer main-content-wrap">
            
              
            
            
<div class="post-actions-wrap">
  <nav >
    <ul class="post-actions post-action-nav">
      
        <li class="post-action">
          
            <a class="post-action-btn btn btn--default tooltip--top" href="https://zgjoget.gitee.io/2022/04/webview/" data-tooltip="WebView" aria-label="NEXT: WebView">
          
              <i class="fa fa-angle-left"></i>
              <span class="hide-xs hide-sm text-small icon-ml">NEXT</span>
            </a>
        </li>
        <li class="post-action">
          
            <a class="post-action-btn btn btn--default tooltip--top" href="https://zgjoget.gitee.io/2022/03/multimedia/" data-tooltip="Multimedia" aria-label="PREVIOUS: Multimedia">
          
              <span class="hide-xs hide-sm text-small icon-mr">PREVIOUS</span>
              <i class="fa fa-angle-right"></i>
            </a>
        </li>
      
    </ul>
  </nav>
<ul class="post-actions post-action-share" >
  
    <li class="post-action hide-lg hide-md hide-sm">
      <a class="post-action-btn btn btn--default btn-open-shareoptions" href="#btn-open-shareoptions" aria-label="Share this post">
        <i class="fa fa-share-alt" aria-hidden="true"></i>
      </a>
    </li>
    
      <li class="post-action hide-xs">
        <a class="post-action-btn btn btn--default" target="new" href="https://www.facebook.com/sharer/sharer.php?u=https://zgjoget.gitee.io/2022/04/service/" title="Share on Facebook" aria-label="Share on Facebook">
          <i class="fab fa-facebook-square" aria-hidden="true"></i>
        </a>
      </li>
    
      <li class="post-action hide-xs">
        <a class="post-action-btn btn btn--default" target="new" href="https://twitter.com/intent/tweet?text=https://zgjoget.gitee.io/2022/04/service/" title="Share on Twitter" aria-label="Share on Twitter">
          <i class="fab fa-twitter" aria-hidden="true"></i>
        </a>
      </li>
    
      <li class="post-action hide-xs">
        <a class="post-action-btn btn btn--default" target="new" href="https://www.linkedin.com/sharing/share-offsite/?url=https://zgjoget.gitee.io/2022/04/service/" title="Share on Linkedin" aria-label="Share on Linkedin">
          <i class="fab fa-linkedin" aria-hidden="true"></i>
        </a>
      </li>
    
  
  
    <li class="post-action">
      <a class="post-action-btn btn btn--default" href="#disqus_thread" aria-label="Leave a comment">
        <i class="far fa-comment"></i>
      </a>
    </li>
  
  <li class="post-action">
    
      <a class="post-action-btn btn btn--default" href="#top" aria-label="Back to top">
      <i class="fa fa-arrow-up" aria-hidden="true"></i>
    
    </a>
  </li>
</ul>
</div>


            
  
    <div id="disqus_thread">
      <noscript>Please enable JavaScript to view the comments powered by Disqus.</noscript>
    </div>
    <script type="text/javascript">
      var disqus_config = function() {
        this.page.url = 'https:\/\/zgjoget.gitee.io\/2022\/04\/service\/';
        
          this.page.identifier = '\/2022\/04\/service\/'
        
      };
      (function() {
        
        
        if (["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1) {
          document.getElementById('disqus_thread').innerHTML = 'Disqus comments not available by default when the website is previewed locally.';
          return;
        }
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        var disqus_shortname = 'zgjoget9-github-io';
        dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
      })();
    </script>
  


          </div>
        </article>
        <footer id="footer" class="main-content-wrap">
  <span class="copyrights">
    &copy; 2022 Zhang Gaojie. All Rights Reserved
  </span>
</footer>

      </div>
      <div id="bottom-bar" class="post-bottom-bar" data-behavior="4">
        
<div class="post-actions-wrap">
  <nav >
    <ul class="post-actions post-action-nav">
      
        <li class="post-action">
          
            <a class="post-action-btn btn btn--default tooltip--top" href="https://zgjoget.gitee.io/2022/04/webview/" data-tooltip="WebView" aria-label="NEXT: WebView">
          
              <i class="fa fa-angle-left"></i>
              <span class="hide-xs hide-sm text-small icon-ml">NEXT</span>
            </a>
        </li>
        <li class="post-action">
          
            <a class="post-action-btn btn btn--default tooltip--top" href="https://zgjoget.gitee.io/2022/03/multimedia/" data-tooltip="Multimedia" aria-label="PREVIOUS: Multimedia">
          
              <span class="hide-xs hide-sm text-small icon-mr">PREVIOUS</span>
              <i class="fa fa-angle-right"></i>
            </a>
        </li>
      
    </ul>
  </nav>
<ul class="post-actions post-action-share" >
  
    <li class="post-action hide-lg hide-md hide-sm">
      <a class="post-action-btn btn btn--default btn-open-shareoptions" href="#btn-open-shareoptions" aria-label="Share this post">
        <i class="fa fa-share-alt" aria-hidden="true"></i>
      </a>
    </li>
    
      <li class="post-action hide-xs">
        <a class="post-action-btn btn btn--default" target="new" href="https://www.facebook.com/sharer/sharer.php?u=https://zgjoget.gitee.io/2022/04/service/" title="Share on Facebook" aria-label="Share on Facebook">
          <i class="fab fa-facebook-square" aria-hidden="true"></i>
        </a>
      </li>
    
      <li class="post-action hide-xs">
        <a class="post-action-btn btn btn--default" target="new" href="https://twitter.com/intent/tweet?text=https://zgjoget.gitee.io/2022/04/service/" title="Share on Twitter" aria-label="Share on Twitter">
          <i class="fab fa-twitter" aria-hidden="true"></i>
        </a>
      </li>
    
      <li class="post-action hide-xs">
        <a class="post-action-btn btn btn--default" target="new" href="https://www.linkedin.com/sharing/share-offsite/?url=https://zgjoget.gitee.io/2022/04/service/" title="Share on Linkedin" aria-label="Share on Linkedin">
          <i class="fab fa-linkedin" aria-hidden="true"></i>
        </a>
      </li>
    
  
  
    <li class="post-action">
      <a class="post-action-btn btn btn--default" href="#disqus_thread" aria-label="Leave a comment">
        <i class="far fa-comment"></i>
      </a>
    </li>
  
  <li class="post-action">
    
      <a class="post-action-btn btn btn--default" href="#top" aria-label="Back to top">
      <i class="fa fa-arrow-up" aria-hidden="true"></i>
    
    </a>
  </li>
</ul>
</div>


      </div>
      
<div id="share-options-bar" class="share-options-bar" data-behavior="4">
  <i id="btn-close-shareoptions" class="fa fa-times"></i>
  <ul class="share-options">
    
      <li class="share-option">
        <a class="share-option-btn" target="new" href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fzgjoget.gitee.io%2F2022%2F04%2Fservice%2F" aria-label="Share on Facebook">
          <i class="fab fa-facebook-square" aria-hidden="true"></i><span>Share on Facebook</span>
        </a>
      </li>
    
      <li class="share-option">
        <a class="share-option-btn" target="new" href="https://twitter.com/intent/tweet?text=https%3A%2F%2Fzgjoget.gitee.io%2F2022%2F04%2Fservice%2F" aria-label="Share on Twitter">
          <i class="fab fa-twitter" aria-hidden="true"></i><span>Share on Twitter</span>
        </a>
      </li>
    
      <li class="share-option">
        <a class="share-option-btn" target="new" href="https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fzgjoget.gitee.io%2F2022%2F04%2Fservice%2F" aria-label="Share on Linkedin">
          <i class="fab fa-linkedin" aria-hidden="true"></i><span>Share on Linkedin</span>
        </a>
      </li>
    
  </ul>
</div>
<div id="share-options-mask" class="share-options-mask"></div>


    </div>
    
    <div id="about">
  <div id="about-card">
    <div id="about-btn-close">
      <i class="fa fa-times"></i>
    </div>
    
      <img id="about-card-picture" src="https://zgjoget.gitee.io/img/avatar.jpg" alt="Author&#39;s picture" />
    
    <h4 id="about-card-name">Zhang Gaojie</h4>
    
      <div id="about-card-bio">A Computer-science and Cyber-security novice</div>
    
    
      <div id="about-card-job">
        <i class="fa fa-briefcase"></i>
        <br/>
        Huazhong University of Science and Technology
      </div>
    
    
      <div id="about-card-location">
        <i class="fa fa-map-marker-alt"></i>
        <br/>
        Wuhan, China
      </div>
    
  </div>
</div>

    

    
  
    
      <div id="cover" style="background-image:url('https://zgjoget.gitee.io/images/cover.jpg');"></div>
    
  


    
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/highlight.min.js" integrity="sha512-z+/WWfyD5tccCukM4VvONpEtLmbAm5LDu7eKiyMQJ9m7OfPEDL7gENyDRL3Yfe8XAuGsS2fS4xSMnl6d30kqGQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js" integrity="sha512-uURl+ZXMBrF4AwGaWmEetzrd+J5/8NRkWAvJx5sbPSSuOb0bZLqf+tOzniObO00BjHa/dD7gub9oCGMLPQHtQA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>


<script src="https://zgjoget.gitee.io/js/script-yqzy9wdlzix4lbbwdnzvwx3egsne77earqmn73v9uno8aupuph8wfguccut.min.js"></script>


  
    <script async crossorigin="anonymous" defer integrity="sha512-gE8KAQyFIzV1C9+GZ8TKJHZS2s+n7EjNtC+IMRn1l5+WYJTHOODUM6JSjZhFhqXmc7bG8Av6XXpckA4tYhflnw==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/apache.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-EWROca+bote+7Oaaar1F6y74iZj1r1F9rm/ly7o+/FwJopbBaWtsFDmaKoZDd3QiGU2pGacBirHJNivmGLYrow==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/go.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-GDVzAn0wpx1yVtQsRWmFc6PhJiLBPdUic+h4GWgljBh904O3JU10fk9EKNpVyIoPqkFn54rgL2QBG4BmUTMpiQ==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/http.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-UgZlma8NzkrDb/NWgmLIcTrH7i/CSnLLDRFqCSNF5NGPpjKmzyM25qcoXGOup8+cDakKyaiTDd7N4dyH4YT+IA==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/less.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-lot9koe73sfXIrUvIPM/UEhuMciN56RPyBdOyZgfO53P2lkWyyXN7J+njcxIIBRV+nVDQeiWtiXg+bLAJZDTfg==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/nginx.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-Zd3e7XxHP00TD0Imr0PIfeM0fl0v95kMWuhyAS3Wn1UTSXTkz0OhtRgBAr4JlmADRgiXr4x7lpeUdqaGN8xIog==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/puppet.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-qtqDO052iXMSP+5d/aE/jMtL9vIIGvONgTJziC2K/ZIB1yEGa55WVxGE9/08rSQ62EoDifS9SWVGZ7ihSLhzMA==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/scss.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-1NmkjnEDnwwwcu28KoQF8vs3oaPFokQHbmbtwGhFfeDsQZtVFI8zW2aE9O8yMYdpdyKV/5blE4pSWw4Z/Sv97w==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/stylus.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-B2wSfruPjr8EJL6IIzQr1eAuDwrsfIfccNf/LCEdxELCgC/S/ZMt/Uvk80aD79m7IqOqW+Sw8nbkvha20yZpzg==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/swift.min.js"></script>
  

  
    <script async crossorigin="anonymous" defer integrity="sha512-28oDiQZGKUVN6wQ7PSLPNipOcmkCALXKwOi7bnkyFf8QiMZQxG9EQoy/iiNx6Zxj2cG2SbVa4dXKigQhu7GiFw==" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.1.0/languages/yaml.min.js"></script>
  


<script>
$(document).ready(function() {
  hljs.configure({ classPrefix: '', useBR: false });
  $('pre.code-highlight > code, pre > code').each(function(i, block) {
    if (!$(this).hasClass('codeblock')) {
      $(this).addClass('codeblock');
    }
    hljs.highlightBlock(block);
  });
});
</script>




    
  </body>
</html>

